// Animates white pixels to simulate flying through a star field

#include <SPI.h>
#include <TFT_eSPI.h>

// With 1024 stars the update rate is ~65 frames per second
#define NSTARS 1024
char sx[NSTARS] = {};
char sy[NSTARS] = {};
char sz[NSTARS] = {};

char zas, zbs, zcs, zxs;

// Fast 0-255 random number generator from http://eternityforest.com/Projects/rng.php:
char __attribute__((always_inline)) rng() {
    zxs++;
    zas = (zas ^ zcs ^ zxs);
    zbs = (zbs + zas);
    zcs = (zcs + (zbs >> 1)^zas);
    return zcs;
}

void start_setup() {
    zas = random(256);
    zbs = random(256);
    zcs = random(256);
    zxs = random(256);
}

void start_loop() {
    unsigned long t0 = micros();
    char spawnDepthVariation = 255;

    for (int i = 0; i < NSTARS; ++i) {
        if (sz[i] <= 1) {
            sx[i] = 160 - 120 + rng();
            sy[i] = rng();
            sz[i] = spawnDepthVariation--;
        } else {
            int old_screen_x = ((int)sx[i] - 160) * 256 / sz[i] + 160;
            int old_screen_y = ((int)sy[i] - 120) * 256 / sz[i] + 120;

            // This is a faster pixel drawing function for occassions where many single pixels must be drawn
            tft.drawPixel(old_screen_x, old_screen_y, TFT_BLACK);

            sz[i] -= 2;
            if (sz[i] > 1) {
                int screen_x = ((int)sx[i] - 160) * 256 / sz[i] + 160;
                int screen_y = ((int)sy[i] - 120) * 256 / sz[i] + 120;

                if (screen_x >= 0 && screen_y >= 0 && screen_x < 320 && screen_y < 240) {
                    char r, g, b;
                    r = g = b = 255 - sz[i];
                    tft.drawPixel(screen_x, screen_y, tft.color565(r, g, b));
                } else {
                    sz[i] = 0;    // Out of screen, die.
                }
            }
        }
    }
    unsigned long t1 = micros();
}
